package com.bblocks.util;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * kryo序列工具类
 */
public class KryoSerializer {

	private static final ThreadLocal<Kryo> kryos = new ThreadLocal<Kryo>() {
		protected Kryo initialValue() {
			Kryo kryo = new Kryo();
			// configure kryo instance, customize settings
			kryo.setRegistrationRequired(false);//关闭注册行为
			kryo.setReferences(true);//支持循环引用
			return kryo;
		};
	};


	private static class LazyHolder  {
		private static final KryoSerializer INSTANCE = new KryoSerializer();
	}
	private KryoSerializer (){}

	public static final KryoSerializer getInstance() {
		return LazyHolder.INSTANCE;
	}

	public byte[] serialize(Object obj) {
		Kryo kryo = kryos.get();
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		Output output = new Output(byteArrayOutputStream);//<1>
		kryo.writeClassAndObject(output, obj);//<2>
		output.close();
		return byteArrayOutputStream.toByteArray();
	}

	public void serialize(Object obj, OutputStream byteArrayOutputStream) {
		Kryo kryo = kryos.get();
		Output output = new Output(byteArrayOutputStream);//<1>
		kryo.writeClassAndObject(output, obj);//<2>
		output.close();
	}

	public <T> T deserialize(byte[] bytes) {
		Kryo kryo = kryos.get();
		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
		return deserialize(byteArrayInputStream);
	}

	public <T> T deserialize(InputStream inputStream) {
		try(Input input = new Input(inputStream);){
			Kryo kryo = kryos.get();
			return (T) kryo.readClassAndObject(input);
		}
	}
}
